package mq.demo04_公平转发;

import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import mq.common.ChannelFactory;


/**
 * @author zhenglian
 * <p>
 * 转载： http://blog.720ui.com/2017/rabbitmq_action_02_workqueues/
 * <p>
 * 摘要：
 * QoS（Quality of Service）是服务质量的简称。
 * 对于网络业务来说，服务质量包括哪些方面呢？
 * 从传统意义上来讲，无非就是传输的带宽、传送的时延、数据的丢包率等，而提高服务质量无非也就是保证传输的带宽，降低传送的时延，降低数据的丢包率以及时延抖动等。
 * 广义上讲，服务质量涉及网络应用的方方面面，只要是对网络应用有利的措施，其实都是在提高服务质量。因此，从这个意义上来说，防火墙、策略路由、快速转发等也都是提高网络业务服务质量的措施之一。
 * <p>
 * 轮询调度的问题：
 * 调度仍然无法正常工作。例如在两个工作线程的情况下，一个工作线程将不断忙碌，另一个工作人员几乎不会做任何工作。那么，RabbitMQ 不知道什么情况，还会平均分配消息。
 * 这是因为当消息进入队列时，RabbitMQ 只会分派消息。它不看消费者的未确认消息的数量。它只是盲目地向第 n 个消费者发送每个第 n 个消息。
 * 为了解决这样的问题，我们可以使用 basicQos 方法，并将传递参数为 prefetchCount = 1。
 * 这样告诉 RabbitMQ 不要一次给一个工作线程多个消息。换句话说，在处理并确认前一个消息之前，不要向工作线程发送新消息。相反，它将发送到下一个还不忙的工作线程。
 * <p>
 * 关键代码：
 * int prefetchCount = 1;
 * channel.basicQos(prefetchCount);
 * @see Channel#basicQos
 */
public class FairWorker {

    private final static String QUEUE_NAME = "hello_world";

    @SneakyThrows
    public static void main(String[] args) {

        Channel channel = ChannelFactory.newInstance("localhost");
        // 指定一个队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        // 公平转发
        int prefetchCount = 1;
        channel.basicQos(prefetchCount);
        // 发送消息
        for (int i = 10; i > 0; i--) {
            String message = "Liang:" + i;
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
        }
        ChannelFactory.closeChannel();

    }
}
